@inherits TestComponentBase

@code {
    MockJsRuntimeInvokeHandler MockJsRuntime { get; set; } = default!;

    void Setup()
    {
        MockJsRuntime = Services.AddMockJsRuntime();
    }
}

<Fixture Setup="Setup" Test="Test001"
         Description="Given no parameters, Alert renders its basic markup, including dismiss button">
    <ComponentUnderTest>
        <Alert />
    </ComponentUnderTest>
    <Fragment Id="expected">
        <div role="alert" class="alert alert-info alert-dismissible fade show">
            <div class="alert-content"></div>
            <button type="button" class="close" aria-label="Close">
                <span aria-hidden="true">&times;</span>
            </button>
        </div>
    </Fragment>
</Fixture>
@code {
    void Test001()
    {
        // Arrange and act
        var cut = GetComponentUnderTest<Alert>();

        // Assert
        IRenderedFragment expected = GetFragment("expected");
        cut.MarkupMatches(expected);
    }
}

<Fixture Setup="Setup" Test="Test002"
         Description="Given a component as Child Content,
                      Alert renders it inside its alert-content element">
    <ComponentUnderTest>
        <Alert>
            <Paragraph IsLast="true">
                @testContent
            </Paragraph>
        </Alert>
    </ComponentUnderTest>
    <Fragment>
        <Paragraph IsLast="true">
            @testContent
        </Paragraph>
    </Fragment>
</Fixture>
@code {
    string testContent = ".NET Conf: Focus on Blazor is a free ...";
    void Test002()
    {
        // Arrange and act
        var cut = GetComponentUnderTest<Alert>();

        // Assert
        var actual = cut.Find(".alert-content > p").TextContent.Trim();
        Assert.Equal(testContent, actual);

        IRenderedFragment expected = GetFragment();
        cut.Find(".alert-content > p").MarkupMatches(expected);
    }
}

<Fixture Setup="Setup" Test="Test003"
         Description="Given Child Content as input, Alert renders it inside its alert-content element">
    <ComponentUnderTest>
        <Alert>
            @testContent
        </Alert>
    </ComponentUnderTest>
</Fixture>
@code {
    void Test003()
    {
        // Arrange and act
        var cut = GetComponentUnderTest<Alert>();

        // Assert
        // Verify by looking at the content and handling whitespace
        var actual = cut.Find(".alert-content").TextContent.Trim();
        Assert.Equal(testContent, actual);

        // Verify using semantic comparison of all child nodes inside content
        cut.Find(".alert-content")
            .ChildNodes
            .MarkupMatches(testContent);
    }
}

<Fixture Setup="Setup" Test="Test004"
         Description="Given a Header as input, Alert renders the header text in the expected element">
    <ComponentUnderTest>
        <Alert Header=@headerText></Alert>
    </ComponentUnderTest>
    <Fragment>
        <h4 class="alert-heading">@headerText</h4>
    </Fragment>
</Fixture>
@code {
    string headerText = "It is time to focus on Blazor";
    void Test004()
    {
        // Arrange and Act
        var cut = GetComponentUnderTest<Alert>();

        // Assert
        string expected = cut.Find(".alert-heading").TextContent;
        Assert.Equal(headerText, expected);

        var expectedMarkup = GetFragment();
        cut.Find(".alert-heading").MarkupMatches(expectedMarkup);
    }
}

<Fixture Setup="Setup"
         Test="Given_Header_and_Localizer_Alert_Uses_Lozalizer_to_lozalize_Header_text">
    <ComponentUnderTest>

        <CascadingValue Value=@localizer>
            <Alert Header=@headerKey></Alert>
        </CascadingValue>

    </ComponentUnderTest>
    <Fragment>
        <h4 class="alert-heading">@localizer[headerKey]</h4>
    </Fragment>
</Fixture>
@code {
    Localizer localizer = new Localizer() { CultureCode = "Yoda" };
    string headerKey = "alert-heading";

    void Given_Header_and_Localizer_Alert_Uses_Lozalizer_to_lozalize_Header_text()
    {
        // Arrange and act
        localizer.Add(headerKey, "Time to focus on Blazor it is.");
        var cut = GetComponentUnderTest<Alert>();

        // Assert
        var expected = cut.Find(".alert-heading").TextContent;
        Assert.Equal(localizer[headerKey], expected);

        var expectedMarkup = GetFragment();
        cut.Find(".alert-heading").MarkupMatches(expectedMarkup);
    }
}

<Fixture Setup="Setup" Test="Test006"
         Description="When dismiss button is clicked, Alert triggers expected callbacks">
    <ComponentUnderTest>

        <Alert OnDismissing="args => dismissingEvent = args"
               OnDismissed="alert => dismissedAlert = alert">
        </Alert>

    </ComponentUnderTest>
</Fixture>
@code {
    DismissingEventArgs? dismissingEvent = default;
    Alert? dismissedAlert = default;

    void Test006()
    {
        // Arrange
        var cut = GetComponentUnderTest<Alert>();

        // Act
        cut.Find("button").Click();

        // Assert
        Assert.NotNull(dismissingEvent);
        Assert.Equal(cut.Instance, dismissedAlert);
    }
}

<Fixture Setup="Setup" Test="Test007"
         Description="When dismiss button is clicked, Alert trigger css animation and finally removes all markup">
    <ComponentUnderTest>

        <Alert>
        </Alert>

    </ComponentUnderTest>
</Fixture>
@code {
    void Test007()
    {
        // arrange
        var plannedInvocation = MockJsRuntime.Setup<object>("window.transitionFinished");
        var cut = GetComponentUnderTest<Alert>();

        // Act
        cut.Find("button").Click();

        // Assert that css transition has started
        Assert.DoesNotContain("show", cut.Find(".alert").ClassList);

        // Act - complete
        WaitForNextRender(() =>
        {
            plannedInvocation.SetResult(default!);
        });

        // Assert that all markup is gone
        cut.MarkupMatches(string.Empty);
    }
}

<Fixture Setup="Setup" Test="Test008"
         Description="Alert can be dismissed via Dismiss() mehod">
    <ComponentUnderTest>
        <Alert @ref="testAlert">
        </Alert>
    </ComponentUnderTest>
</Fixture>
@code {
    Alert? testAlert;
    void Test008()
    {
        // arrange
        var cut = GetComponentUnderTest<Alert>();

        // Act
        testAlert?.Dismiss().Wait();

        // Assert that all markup is gone
        cut.MarkupMatches(string.Empty);
        Assert.False(cut.Instance.IsVisible);
    }
}

<Fixture Setup="Setup" Test="Test009"
         Description="Alert renders correctly when all input is provided">
    <ComponentUnderTest>
        <CascadingValue Value="localizer2">
            <Alert Header="alert-heading" OnDismissing="args => { }" OnDismissed="alert => { }">
                <Paragraph IsLast="true">
                    .NET Conf: Focus on Blazor is a free ...
                </Paragraph>
            </Alert>
        </CascadingValue>
    </ComponentUnderTest>
    <Fragment>
        <div role="alert"class="alert alert-info alert-dismissible fade show">
            <h4 class="alert-heading">@localizer2[headerKey]</h4>
            <div class="alert-content">
                <Paragraph IsLast="true">
                    @testContent
                </Paragraph>
            </div>
            <button type="button"class="close"aria-label="Close">
                <span aria-hidden="true">&times;</span>
            </button>
        </div>
    </Fragment>
</Fixture>
@code {
    Localizer localizer2 = new Localizer() { CultureCode = "Yoda" };

    void Test009()
    {
        // Arrange
        localizer2.Add("alert-heading", "Time to focus on Blazor it is.");

        // Act
        var cut = GetComponentUnderTest<Alert>();

        // Assert
        var expected = GetFragment();
        cut.MarkupMatches(expected);
    }
}